package com.zkyc.framework.website.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zkyc.framework.common.constant.NumberConstant;
import com.zkyc.framework.common.exception.ResultCode;
import com.zkyc.framework.common.mapper.MediaTagMapper;
import com.zkyc.framework.common.mapper.PublicityMeetingMapper;
import com.zkyc.framework.common.mapper.PublicityRefTagMapper;
import com.zkyc.framework.common.pojo.MediaTag;
import com.zkyc.framework.common.pojo.PublicityMeeting;
import com.zkyc.framework.common.pojo.PublicityRefTag;
import com.zkyc.framework.common.pojo.User;
import com.zkyc.framework.common.vo.ResultVO;
import com.zkyc.framework.website.client.UserClient;
import com.zkyc.framework.website.mapper.MediaMapper;
import com.zkyc.framework.website.service.PublicityMeetingService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (PublicityMeeting)表服务实现类
 *
 * @author libingchuan
 * @since 2022-10-10 15:36:04
 */
@Service("publicityMeetingService")
public class PublicityMeetingServiceImpl implements PublicityMeetingService {
    @Resource
    private PublicityMeetingMapper publicityMeetingMapper;

    @Resource
    private PublicityRefTagMapper publicityRefTagMapper;

    @Resource
    private MediaMapper mediaMapper;

    @Resource
    private MediaTagMapper mediaTagMapper;

    @Resource
    private UserClient userClient;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public PublicityMeeting queryById(Integer id) {
        PublicityMeeting publicityMeeting = publicityMeetingMapper.selectById(id);
        QueryWrapper<PublicityMeeting> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pid", publicityMeeting.getId());
        queryWrapper.orderByDesc("order_num");
        List<PublicityMeeting> specialSession = publicityMeetingMapper.selectList(queryWrapper);
        List<PublicityMeeting> collect = specialSession.stream().filter(x -> isNotDate(x.getMeetingDate())).collect(Collectors.toList());
        specialSession.removeIf(x -> isNotDate(x.getMeetingDate()));
        for (PublicityMeeting meeting : specialSession) {
            QueryWrapper<PublicityMeeting> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("pid", meeting.getId());
            queryWrapper1.orderByDesc("order_num");
            meeting.setChildren(publicityMeetingMapper.selectList(queryWrapper1));
        }
        specialSession.addAll(collect);
        publicityMeeting.setChildren(specialSession);
        return publicityMeeting;
    }

    private boolean isNotDate(String meetingDate) {
        try {
            DateUtil.formatDate(DateUtil.parse(meetingDate.replaceAll("年", "-").replaceAll("月", "-").replaceAll("日", "")));
        } catch (Exception e) {
            return true;
        }
        return false;
    }


    /**
     * 查询
     *
     * @return 查询结果
     */
    @Override
    public ResultVO queryList() {
        LambdaQueryWrapper<PublicityMeeting> meetingLqw = new LambdaQueryWrapper<>();
        meetingLqw.orderByDesc(PublicityMeeting::getOrderNum);
        List<PublicityMeeting> publicityMeetings = publicityMeetingMapper.selectList(meetingLqw);
        publicityMeetings.forEach(publicityMeeting -> {
            List tagLists = new LinkedList();
            List tagNames = new LinkedList();
            Integer publicityMeetingId = publicityMeeting.getId();
            List<Integer> tagIdList = publicityRefTagMapper.queryTagIdList(publicityMeetingId);
            for (Integer tagRefId : tagIdList) {
                List list = new LinkedList();

                JSONObject jsonObject = mediaMapper.queryTagByTagId(tagRefId);
                if (jsonObject != null) {
                    if (jsonObject.get("tag_group_id") == null) {
                        continue;
                    }
                    list.add(jsonObject.get("tag_group_id"));
                    list.add(jsonObject.get("id"));
                    tagLists.add(list);
                    tagNames.add(jsonObject.get("media_tag_name"));
                }
            }
            ResultVO<?> userById = userClient.getUserById(publicityMeeting.getOperateUserId());
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(userById));
            User user = JSONObject.parseObject(jsonObject.getString("data"), User.class);
            publicityMeeting.setOperateUserName(user.getUsername());
            publicityMeeting.setTagId(tagLists);
            publicityMeeting.setTagNames(tagNames);
        });
        return ResultVO.data(List2Tree(publicityMeetings));
    }

    @Override
    public ResultVO listByPage(Integer current, Integer size) {
        Page<PublicityMeeting> page = new Page(current, size);
        QueryWrapper<PublicityMeeting> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pid", 0);
        queryWrapper.orderByDesc("order_num");
        Page<PublicityMeeting> page1 = publicityMeetingMapper.selectPage(page, queryWrapper);
        page1.getRecords().forEach(publicityMeeting -> {
            List tagLists = new LinkedList();
            List tagNames = new LinkedList();
            Integer publicityMeetingId = publicityMeeting.getId();
            List<Integer> tagIdList = publicityRefTagMapper.queryTagIdList(publicityMeetingId);
            for (Integer tagRefId : tagIdList) {
                List list = new LinkedList();

                JSONObject jsonObject = mediaMapper.queryTagByTagId(tagRefId);
                if (jsonObject != null) {
                    if (jsonObject.get("tag_group_id") == null) {
                        continue;
                    }
                    list.add(jsonObject.get("tag_group_id"));
                    list.add(jsonObject.get("id"));
                    tagLists.add(list);
                    tagNames.add(jsonObject.get("media_tag_name"));
                }
            }
            ResultVO<?> userById = userClient.getUserById(publicityMeeting.getOperateUserId());
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(userById));
            User user = JSONObject.parseObject(jsonObject.getString("data"), User.class);
            publicityMeeting.setOperateUserName(user.getUsername());
            publicityMeeting.setTagId(tagLists);
            publicityMeeting.setTagNames(tagNames);
        });
        return ResultVO.data(page1);
    }


    /**
     * 新增数据
     *
     * @param publicityMeeting 实例对象
     * @return 实例对象
     */
    @Override
    public ResultVO insert(PublicityMeeting publicityMeeting) {
        if (publicityMeeting == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        try {
            DateTime parse = DateUtil.parse(publicityMeeting.getMeetingDate().replaceAll("年", "-").replaceAll("月", "-").replaceAll("日", ""));
            publicityMeeting.setMeetingDate(DateUtil.formatDate(parse));
            publicityMeeting.setOrderNum(parse.getTime());
        } catch (Exception ignored) {
            publicityMeeting.setOrderNum(System.currentTimeMillis());
        }
        publicityMeetingMapper.insert(publicityMeeting);
        insertTag(publicityMeeting);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private void insertTag(PublicityMeeting publicityMeeting) {
        PublicityRefTag publicityRefTag = new PublicityRefTag();
        if (publicityMeeting.getTagId() != null && publicityMeeting.getTagId().size() > 0) {
            List<List<Integer>> tagIdList = publicityMeeting.getTagId();
            for (List<Integer> integers : tagIdList) {
                publicityRefTag.setPublicityId(publicityMeeting.getId());
                publicityRefTag.setMediaTagId(integers.get(integers.size() - 1));
                publicityRefTagMapper.insert(publicityRefTag);
            }
        } else {
            if (mediaMapper.queryNullTag() == null) {
                MediaTag mediaTag = new MediaTag();
                mediaTag.setId(NumberConstant.NUMBER_0);
                mediaTag.setMediaTagName(" ");
                mediaTagMapper.insert(mediaTag);
            }
            int tagId = mediaTagMapper.selectZero();
            publicityRefTag.setPublicityId(publicityMeeting.getId());
            publicityRefTag.setMediaTagId(tagId);
            publicityRefTagMapper.insert(publicityRefTag);
        }
    }

    /**
     * 修改数据
     *
     * @param publicityMeeting 实例对象
     * @return 实例对象
     */
    @Override
    public ResultVO update(PublicityMeeting publicityMeeting) {
        if (publicityMeeting == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        if (queryById(publicityMeeting.getId()) == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        try {
            publicityMeeting.setMeetingDate(DateUtil.formatDate(DateUtil.parse(publicityMeeting.getMeetingDate().replaceAll("年", "-").replaceAll("月", "-").replaceAll("日", ""))));
        } catch (Exception ignored) {
        }
        publicityMeetingMapper.updateById(publicityMeeting);
        publicityRefTagMapper.deleteByPublicityId(publicityMeeting.getId());
        insertTag(publicityMeeting);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public ResultVO deleteById(Integer id) {
        if (id == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        if (queryById(id) == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        publicityMeetingMapper.deleteById(id);
        publicityRefTagMapper.deleteByPublicityId(id);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    /**
     * stream方法转换成树形结构
     *
     * @param treeList 树结构
     * @return treeList
     */
    public static List<PublicityMeeting> List2Tree(List<PublicityMeeting> treeList) {
        return treeList.stream()
                // 筛选出父节点
                .filter(t -> t.getPid() == 0)
                // 设置父节点的子节点列表
                .peek(item -> item.setChildren(streamGetChildren(item, treeList)))
                .collect(Collectors.toList());
    }

    /**
     * stream 方式递归查找子节点列表
     *
     * @return childrenList
     */
    public static List<PublicityMeeting> streamGetChildren(PublicityMeeting tree, List<PublicityMeeting> treeList) {
        return treeList.stream()
                .filter(t -> t.getPid().equals(tree.getId()))
                .peek(item -> item.setChildren(streamGetChildren(item, treeList)))
                .sorted(Comparator.comparing(PublicityMeeting::getGmtCreated).reversed())
                .collect(Collectors.toList());
    }

    @Override
    public ResultVO upOrDown(PublicityMeeting meeting) {
        Integer meetingId = meeting.getId();
        PublicityMeeting originalMeeting = publicityMeetingMapper.selectById(meetingId);
        if (originalMeeting == null || !"3".equals(originalMeeting.getType())) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        Long originalNum = originalMeeting.getOrderNum();
        LambdaQueryWrapper<PublicityMeeting> meetingLqw = new LambdaQueryWrapper<>();
        meetingLqw.eq(PublicityMeeting::getPid, originalMeeting.getPid()).ne(PublicityMeeting::getId, meetingId);
        if (meeting.getOrderNum() == NumberConstant.NUMBER_0) {
            // 下移
            meetingLqw.le(PublicityMeeting::getOrderNum, originalNum);
            meetingLqw.orderByDesc(PublicityMeeting::getOrderNum);
        } else {
            // 上移
            meetingLqw.ge(PublicityMeeting::getOrderNum, originalNum);
            meetingLqw.orderByAsc(PublicityMeeting::getOrderNum);
        }
        meetingLqw.last("limit 1");
        PublicityMeeting modernMeeting = publicityMeetingMapper.selectOne(meetingLqw);
        if (modernMeeting == null) {
            return ResultVO.fail("该数据无法上移/下移");
        }
        // 交换排序数字
        Long modernNum = modernMeeting.getOrderNum();
        originalMeeting.setOrderNum(modernNum);
        modernMeeting.setOrderNum(originalNum);
        // 更新数据库
        publicityMeetingMapper.updateById(originalMeeting);
        publicityMeetingMapper.updateById(modernMeeting);
        return ResultVO.success(ResultCode.SUCCESS);
    }
}
